/*
    Game服务器  
    Debug模式: node game.js debugger 
    Game模式:  node game.js serverId
*/

global.clone    = require('clone');
global.http     = require('http');
global.util     = require('util');
global.common   = require('./common.js');
global.Player   = require('./logic/player.js').Player;
global.Fighter  = require('./logic/fighter.js').Fighter;
global.Message  = require('./world/message.js').Message;
var http = require('http');
var qs = require('querystring');

global.config   = require(require('fs').existsSync('../config.js') ? '../config.js' : './config.js');

var server  = require('./server.js');
global.logic   = require('./logic');
var world   = require('./world');
var logger  = require('./logger.js');
require('./global.js');

// 数据库,缓存
global.gDBPlat = null;
global.gDBUser = null;
global.gDBAnalysis = null;
global.gDBWorld = null;
global.gDBRank = null;
global.gDBCash = null;
global.gDBLog = null;
global.gCache = null;

global.gPlayers = null;
global.gServerStartTime = common.getTime();

// World对象
global.gRank = null;
global.gMine = null;
global.gTowerRank = null;
global.gReplay = null;
global.gMessage = null;
global.gUserInfo = null;
global.gCombine = null;
global.gTopOne2 = null;
global.gLeagueWar = null;
global.gLeagueBoss = null;
global.gActivity = null;
global.gTowerActivityRank = null;
global.gFightForceRank = null;
global.gLevelRank = null;
global.gWorldBoss = null;
global.gTowerRank2 = null;
global.gInvite = null;
global.gYearBoss = null;
global.gFriend = null;
global.gInsurgency = null;
global.gElderSign = null;
global.gAssistMine = null;
global.gHeroLog = null;
global.gHoroscopefarmTree = null;

server.loadGlobalServerConf();
logger.init({name:'game', debug:{backups:20}, error:{backups:4}, record:{}, audit:{}});
global.gWealthMessages = new (require('./logic/activity.js').WealthMessage)(); 


(function main(){
    // Debug 模式
    var isDebug = false;
    if( process.argv.indexOf('debugger') > 0 ) {
        isDebug = true;
    }

    server.loadCache(function(cache){
        global.gCache = cache;
        INFO('redis connected');
    });

    server.loadConf();
    for (var mod in logic) {
        var initHandler = logic[mod]._initRuntime;
        if (initHandler) {
            initHandler();
        }
    }

    server.loadDB(function(db){
        // 启动Game服务器

        INFO('mongodb connected');
        global.gDBPlat = db.collection('plat');
        global.gDBUser = db.collection('user');
        global.gDBWorld = db.collection('world');
        global.gDBAnalysis = db.collection('analysis');
        global.gDBCash = db.collection('cash');
        global.gDBLog = db.collection('log');

        global.gMessage = new Message();

        var PlayerManager   = require('./logic/player.js').PlayerManager;
        global.gPlayers = new PlayerManager();
        
        if( isDebug ) {
            loadWorld(require('./debug.js').Debug);
            
            return;
        }

        loadWorld(startGame);

        // 踢掉已经下线的玩家,判断条件: 5分钟没有发出任何操作的用户
        // @toDo 优化到10分钟
        setInterval(function(){
            gPlayers.kick();
            gLeague.checkApplyingTime();
        }, 1000*60);

        timer_hour();
    }, 5);
})();

function startGame() {
    var serverName = 'game';
    var port = config.GameListen;
    var exec = require('child_process').exec;

    var wserver = server.startWebServer(serverName, port, '0.0.0.0', function(query, res, resp){
        if( query.mod == 'gm' && query.act == 'online' ) {
            res.writeHead(200, common.defaultHeaders);
            res.end("" + gPlayers.onlineCount());
            return;
        }
        
        do {
            // 判断参数
            if( query.mod != 'gm' ) {
                if( !query.auth_key || !query.auth_time ) {
                    resp.nolog = 1; resp.code = 2; resp.desc = 'no auth_key, auth_time'; break;
                }

                if( !common.verifyAuth(query.uid, query.auth_key, query.auth_time) ) {
                    resp.nolog = 1; resp.code = 2; resp.desc = 'auth fail'; break;
                }

                // 服务器重启后,踢掉所有人
                if( isNaN(query.auth_time) || parseInt(query.auth_time) < gServerStartTime ) {
                    resp.nolog = 1; resp.code = 2; resp.desc = 'auth timeout'; break;
                }

                if (gConfSwitch.GameAuthEx && !common.verifyGameAuthEx(query.uid, query.auth_time, query.exauth)) {
                    resp.nolog = 1; resp.code = 2; resp.desc = 'exauth fail'; break;
                }
            }

            var logicHandler = null;
            var module = logic[query.mod];

            if( module ) {
                logicHandler = module[query.act];
            }

            if( !logicHandler ) {
                resp.code = 1;
                resp.desc = 'act ' + query.act + ' not support in mod ' + query.mod;
                break;
            }

        }while(false);

        if( resp.code != 0 ) {
            onReqHandled(res, resp);
            return;
        }

        if( (query.mod == 'user' && query.act == 'login') || (query.mod == 'gm' && query.act == 'gm') ) {
            gPlayers.load(query.uid, function(player){
                handleGameReq(player, query, res, resp);
            });
        }else{
            gPlayers.get(query.uid, function(player){
                handleGameReq(player, query, res, resp);
            });
        }
    }, function(callback) {
        // 退出处理
        var forceSave = true;
        var loader = new common.Loader(callback);
        loader.addLoad('empty');    // 防止没有需要Load的时候不结束

        var players = gPlayers.players;
        for(var uid in players ) {
            var player = players[uid];
            loader.addLoad(player.uid);

            player.save(forceSave, function(){
                loader.onLoad(this.uid);
            }.bind(player));
        }

        // 强制保存全局共享数据
        loader.addLoad('data_holder');
        gDataHolder.save(forceSave, function(succ) {
            loader.onLoad('data_holder');
        });
        
        // 强制保存Rank
        loader.addLoad('rank');
        gRank.save(forceSave, function(succ){
            loader.onLoad('rank');
        });

        // 强制保存军团战
        loader.addLoad('league_war');
        gLeagueWar.save(forceSave, function(succ){
            loader.onLoad('league_war');
        });

        //强制保存军团副本
        loader.addLoad('league_duplicate');
        gLeagueDuplicate.save(forceSave, function(succ) {
            loader.onLoad('league_duplicate');
        });

        // 强制保存金矿
        loader.addLoad('mine');
        gMine.save(forceSave, function(succ){
            loader.onLoad('mine');
        });

        // 强制保存军团
        loader.addLoad('league');
        gLeague.save(forceSave, function(succ){
            loader.onLoad('league');
        });

        // 强制保存好友
        loader.addLoad('friend');
        gFriend.save(forceSave, function(succ){
            loader.onLoad('friend');
        });

        // 保存平乱
        loader.addLoad('insurgency');
        gInsurgency.save(forceSave, function(succ){
            loader.onLoad('insurgency');
        });

        // 保存远古封印
        loader.addLoad('eldersign');
        gElderSign.save(forceSave, function(succ){
            loader.onLoad('eldersign');
        });

        // 保存协助开矿
        loader.addLoad('assistmine');
        gAssistMine.save(forceSave, function(succ){
            loader.onLoad('assistmine');
        });

        // 保存英雄志
        //loader.addLoad("herolog");
        //gHeroLog.save(forceSave, function(succ){
        //    loader.onLoad('herolog');
        //});

        // 保存星魂农场-仙灵树
        loader.addLoad('horoscopefarm_tree');
        gHoroscopefarmTree.save(forceSave, function(succ) {
            loader.onLoad('horoscopefarm_tree');
        });


        loader.onLoad('empty');
    });
}

function loadWorld(callback) {

    // 加载全部玩家基本信息, 不需要等待完成
    var UserInfo = require('./world/user.js').UserInfo;
    global.gUserInfo = new UserInfo();
    gUserInfo.init(function(succ){
        if( !succ ) {
            ERROR("can't load user");
            process.exit(-1);
        }
        INFO('user loaded');
    });

    var loader = new common.Loader(function() {
        gDataHolder.check();
        callback();
    });

    // 加载全局共享数据
    loader.addLoad('data_holder');
    var DataHolder = require('./world/dataholder.js').DataHolder;
    global.gDataHolder = new DataHolder;
    gDataHolder.init(function(succ) {
        if (!succ) {
            ERROR("can't load data_holder");
            process.exit(-1);
        }
        INFO('data_holder loaded');
        loader.onLoad('data_holder');
    });

    // 加载金矿
    loader.addLoad('mine');
    var Mine = require('./world/mine.js').Mine;
    global.gMine = new Mine();
    gMine.init(function(succ){
        if( !succ ) {
            ERROR("can't load mine");
            process.exit(-1);
        }
        INFO('mine loaded');
        loader.onLoad('mine');
    });
        
    // 加载排行榜
    loader.addLoad('rank');
    var Rank = require('./world/rank.js').Rank;
    global.gRank = new Rank();
    gRank.init(function(succ){
        if( !succ ) {
            ERROR("can't load rank");
            process.exit(-1);
        }
        INFO('rank loaded');
        loader.onLoad('rank');
    });

    // 加载爬塔排行榜
    loader.addLoad('tower_rank');
    var TowerRank = require('./world/rank.js').TowerRank;
    global.gTowerRank = new TowerRank();
    gTowerRank.init(function(succ){
        if( !succ ) {
            ERROR("can't load tower rank");
            process.exit(-1);
        }
        INFO('tower rank loaded');
        loader.onLoad('tower_rank');
    });

    // 加载军团
    loader.addLoad('league');
    var League = require('./world/league').League;
    global.gLeague = new League();
    gLeague.init(function(succ){
        if( !succ ) {
            ERROR("can't load league");
            process.exit(-1);
        }
        INFO('league loaded');
        loader.onLoad('league');
    });

    // 加载Replay
    loader.addLoad('replay');
    var Replay = require('./world/replay.js').Replay;
    global.gReplay = new Replay();
    gReplay.init(function(succ){
        if( !succ ) {
            ERROR("can't load replay");
            process.exit(-1);
        }
        INFO('replay loaded');
        loader.onLoad('replay');
    });

    // 加载Combine
    loader.addLoad('combine');
    var Combine = require('./world/combine.js').Combine;
    global.gCombine = new Combine();
    gCombine.init(function(succ){
        if( !succ ) {
            ERROR("can't load combine");
            process.exit(-1);
        }
        INFO('combine loaded');
        loader.onLoad('combine');
    });

    // 疯狂擂台 
    loader.addLoad('topone2');
    var TopOne2 = require('./world/rank.js').TopOne2;
    global.gTopOne2 = new TopOne2();
    gTopOne2.init(function(succ){
        if( !succ ) {
            ERROR("can't load topone2");
            process.exit(-1);
        }
        INFO('topone2 loaded');
        loader.onLoad('topone2');
    });

    //加载军团战
    loader.addLoad('league_war');
    var LeagueWar = require('./world/leaguewar.js').LeagueWar;
    global.gLeagueWar = new LeagueWar();
    gLeagueWar.init(function(succ) {
        if (!succ) {
            ERROR("can't load league_war");
            process.exit(-1);
        }
        INFO('league_war loaded');
        loader.onLoad('league_war');
    });

    // 加载军团boss
    loader.addLoad('league_boss');
    var LeagueBoss = require('./world/boss.js').LeagueBoss;
    global.gLeagueBoss = new LeagueBoss();
    gLeagueBoss.init(function(succ) {
        if (!succ) {
            ERROR("can't load league_boss");
            process.exit(-1);
        }
        INFO('league_boss loaded');
        loader.onLoad('league_boss');
    });

    // 加载军团副本
    loader.addLoad('league_duplicate');
    var LeagueDuplicate = require('./world/leagueduplicate.js').LeagueDuplicate;
    global.gLeagueDuplicate = new LeagueDuplicate();
    gLeagueDuplicate.init(function(succ) {
        if (!succ) {
            ERROR("can't load league_duplicate");
            process.exit(-1);
        }

        INFO('league_duplicate loaded');
        loader.onLoad('league_duplicate');
    });

    // 加载活动
    loader.addLoad('activity');
    var Activity = require('./world/activity.js').Activity;
    global.gActivity = new Activity();
    gActivity.init(function(succ) {
        if (!succ) {
            ERROR("can't load activity");
            process.exit(-1);
        }
        INFO('activity loaded');
        loader.onLoad('activity');
    });

    // 加载勇闯重楼排名活动
    loader.addLoad('tower_activity_rank');
    var TowerActivityRank = require('./world/rank.js').TowerActivityRank;
    global.gTowerActivityRank = new TowerActivityRank();
    gTowerActivityRank.init(function(succ) {
        if (!succ) {
            ERROR("can't load tower activity rank");
            process.exit(-1);
        }
        INFO('tower activity rank loaded');
        loader.onLoad('tower_activity_rank');
    });

    // 加载战力大比拼活动排名
    loader.addLoad('fight_force_rank');
    var FightForceRank = require('./world/rank.js').FightForceRank;
    global.gFightForceRank = new FightForceRank();
    gFightForceRank.init(function(succ) {
        if (!succ) {
            ERROR("can't load fight force rank");
            process.exit(-1);
        }
        INFO('fight force rank loaded');
        loader.onLoad('fight_force_rank');
    });
    
    // 加载冲级大赛
    loader.addLoad('level_rank');
    var LevelRank = require('./world/rank.js').LevelRank;
    global.gLevelRank = new LevelRank();
    gLevelRank.init(function(succ) {
        if (!succ) {
            ERROR("can't load level_rank");
            process.exit(-1);
        }
        INFO('level_rank loaded');
        loader.onLoad('level_rank');
    });

    // 加载世界boss
    loader.addLoad('worldboss');
    var WorldBoss = require('./world/worldboss.js').WorldBoss;
    global.gWorldBoss = new WorldBoss();
    gWorldBoss.init(function(succ) {
        if (!succ) {
            ERROR("can't load world boss");
            process.exit(-1);
        }
        INFO('world boss loaded');
        loader.onLoad('worldboss');
    });

    // 加载新勇闯重楼排名
    loader.addLoad('tower_rank2');
    var TowerRank2 = require('./world/rank.js').TowerRank2;
    global.gTowerRank2 = new TowerRank2();
    gTowerRank2.init(function(succ) {
        if (!succ) {
            ERROR("can't load tower rank2");
            process.exit(-1);
        }
        INFO('tower rank2 loaded');
        loader.onLoad('tower_rank2');
    });

    // 加载邀请
    loader.addLoad('invite');
    var Invite = require('./world/user.js').Invite;
    global.gInvite = new Invite();
    gInvite.init(function(succ) {
        if (!succ) {
            ERROR("can't load invite");
            process.exit(-1);
        }
        INFO('invite loaded');
        loader.onLoad('invite');
    });

    // 加载年兽boss
    loader.addLoad('yearboss');
    var YearBoss = require('./world/activity.js').YearBoss;
    global.gYearBoss = new YearBoss();
    gYearBoss.init(function(succ) {
        if (!succ) {
            ERROR("can't load year boss");
            process.exit(-1);
        }
        INFO('year boss loaded');
        loader.onLoad('yearboss');
    });

    // 加载好友
    loader.addLoad('friend');
    var Friend = require('./world/user.js').Friend;
    global.gFriend = new Friend();
    gFriend.init(function(succ) {
        if (!succ) {
            ERROR("can't load friend");
            process.exit(-1);
        }
        INFO('friend loaded');
        loader.onLoad('friend');
    });

    // 加载平乱
    loader.addLoad('insurgency');
    var Insurgency = require('./world/insurgency.js').Insurgency;
    global.gInsurgency = new Insurgency();
    gInsurgency.init(function(){
        INFO('insurgency loaded');
        loader.onLoad('insurgency');
    });

    // 加载远古封印
    loader.addLoad('eldersign');
    var ElderSign = require('./world/eldersign.js').ElderSign;
    global.gElderSign = new ElderSign();
    gElderSign.init(function(){
        INFO('eldersign loaded');
        loader.onLoad('eldersign');
    });

    // 加载协助开矿
    loader.addLoad('assistmine');
    var AssistMine = require('./world/assistmine.js').AssistMine;
    global.gAssistMine = new AssistMine();
    gAssistMine.init(function(){
        INFO('assistmine loaded');
        loader.onLoad('assistmine');
    });

    // 加载英雄志
    //loader.addLoad("herolog");
    var HeroLog = require('./world/herolog.js').HeroLog;
    global.gHeroLog = new HeroLog();
    //gHeroLog.init(function(){
    //    INFO('herolog loaded');
    //    loader.onLoad('herolog');
    //});

    // 加载星魂农场-仙灵树
    var HoroscopefarmTree = require('./world/horoscopefarm.js').HoroscopefarmTree;
    global.gHoroscopefarmTree = new HoroscopefarmTree();
    loader.addLoad(gHoroscopefarmTree.getId());
    gHoroscopefarmTree.load(function() {
        INFO(util.format('%s loaded', gHoroscopefarmTree.getId()));
        loader.onLoad(gHoroscopefarmTree.getId());
    });
}

function handleGameReq(player, query, res, resp) {
    /*
    验证请求的基本参数和状态
    */
    if (!player) {
        resp.code = 1; resp.desc = 'system_busy'; 
        onReqHandled(res, resp); 
        return;
    }

    if( player.saveError ) {
        gPlayers.unload(player.uid);
        resp.code = 1; resp.desc = 'last save error';
        onReqHandled(res, resp);
        return;
    }

    if( player.lock ) {
        resp.code = 1; resp.desc = 'lock';
        onReqHandled(res, resp);
        return;
    }
    
    if( !config.NotVerifyHack ) {
        if( !player.hackVerifyKey ) {
            player.hackVerifyKey = common.getGameHackKey(player.uid);
        }

        if((query.mod != 'gm') && !common.verifyGameHack(query.uid, player.hackVerifyKey, query.seq, query.mod, query.act, query.key) ) {
            player.hackVerifyKey = common.getGameHackKey(player.uid);
            if (!common.verifyGameHack(query.uid, player.hackVerifyKey, query.seq, query.mod, query.act, query.key)) {
                resp.code = 1; resp.desc = 'key';
                onReqHandled(res, resp);
                return;
            }
        }
    }

    // 处理时间变量
    player.clientIP = query.clientIP || "0.0.0.0";
    player.checkDailyVars();
    var nowStamp = Date.getStamp();
    var nowQuarter = Math.floor(nowStamp/300);
    if (nowQuarter != player.lastMsgQuarter) {
        player.lastMsgQuarter = nowQuarter;
        player.quarterActionScore = 0;
    }

    /*
    防外挂处理,限制请求频率及每日异常次数
    */
    if (query.mod != 'gm') {
        if (gConfGlobal.GameGuardExceptScore) {
            if (player.getDailyVar('except_score') > gConfGlobal.GameGuardExceptScore) {
                resp.code = 1; resp.desc = 'except_limit';
                onReqHandled(res, resp);
                return;
            }
        }

        if (gConfGlobal.GameGuardActionScore) {
            var blockTime = 1800;
            if (-1 == player.quarterActionScore) {
                gPlayers.unload(player.uid);
                resp.code = 1; resp.desc = 'blocked_user'; resp.data.stamp = nowStamp + blockTime;
                onReqHandled(res, resp);
                return;
            }

            if (player.quarterActionScore >= gConfGlobal.GameGuardActionScore) {
                player.quarterActionScore = -1;
                gPlayers.unload(player.uid);
                resp.code = 1; resp.desc = 'blocked_user'; resp.data.stamp = nowStamp + blockTime;
                onReqHandled(res, resp);
                var url = util.format('http://0.0.0.0:%d?&act=%s&method=%s&uid=%d&key=%s&blocktime=%d', 
                    config.GatewayListen, 'gm', 'block', query.uid, config.GMAuth, blockTime);
                common.httpGet(url, function(data) {}, true);
                return;
            }
        }
    }

    /*
    处理消息
    */
    player.lastActive = common.getTime();
    player.lock = true;
    player.action.mod = query.mod;
    player.action.act = query.act;
    player.action.score = 1;

    var logicHandler = logic[query.mod][query.act];
    logicHandler(player, query, resp, function(){
        player.lock = false;
        if( resp.code != 0 ) {
            player.cleanDirty();
            var actionExcept = gModExcept[query.mod]||1;
            player.addDailyVar('except_score', actionExcept);
            player.action.score += 20;
        }else{
            var respCommon = {};
            resp.data.common = respCommon;

            var dailyVars = player.user.daily_vars;
            if (dailyVars) {
                respCommon.day = dailyVars.day;
            }

            var finishedTask = player.checkTask(); 
            if( finishedTask.length > 0) {
                resp.finished_task = finishedTask; 
            }

            var tutorialLevelPackAwards = player.checkTutorialLevelPackAwards();
            if( tutorialLevelPackAwards.length > 0 ) {
                resp.data.tutorial_level_pack_awards = tutorialLevelPackAwards; 
            }

            if (player.finishedAchievements.length > 0) {
                resp.data.common.achievements = clone(player.finishedAchievements);
                player.finishedAchievements = [];
            }

            player.doingTasks = [];
            
            var forceSave = false;
            if (query.mod == 'gm') {
                forceSave = true;
            } else {
                var playerStatus = player.status;
                if (playerStatus.awards) {
                    respCommon.awards = clone(playerStatus.awards);
                    delete playerStatus.awards;
                }

                if (playerStatus.notice) {
                    respCommon.notice = clone(playerStatus.notice);
                    delete playerStatus.notice;
                }
            }

            player.save(forceSave);
        }
        
        player.quarterActionScore += player.action.score;
        
        var useGzip = true;
        if( query.mod == 'gm' ) {
            useGzip = false;
        }
        onReqHandled(res, resp, useGzip);
    });
};

global.doPVP = function(uid, enemyid, callback) {
    var player, enemy; 

    var loader = new common.Loader(function(){
        if( !player || !enemy ) {
            callback && callback(null);
            return;
        }

        var playerFighter = new Fighter();
        playerFighter.initWithPlayer(player);
        var enemyFighter = new Fighter();
        enemyFighter.initWithPlayer(enemy);

        gUserInfo.updatePlayer(player);
        gUserInfo.updatePlayer(enemy);
    

        var battleReport = playerFighter.fight(enemyFighter);
        callback && callback(battleReport);
    });

    loader.addLoad('player');
    loader.addLoad('enemy');

    gPlayers.get(uid, function(_player){
        player = _player;
        loader.onLoad('player');
    });

    gPlayers.get(enemyid, function(_player){
        enemy = _player;
        loader.onLoad('enemy');
    });
}

global.fightLeagueWar = function(uid, enemyid, isAddAttack, addToWhich, callback) {
    var player, enemy; 

    var loader = new common.Loader(function(){
        if( !player || !enemy ) {
            callback && callback(null);
            return;
        }
        
        var playerFighter = new Fighter();
        playerFighter.initWithPlayer(player, null, false, ((isAddAttack && 'attack' == addToWhich) ? 'league_war' : null));
        var enemyFighter = new Fighter();
        enemyFighter.initWithPlayer(enemy, null, false, ((isAddAttack && 'defence' == addToWhich) ? 'league_war' : null));

        gUserInfo.updatePlayer(player);
        gUserInfo.updatePlayer(enemy);
    

        var battleReport = playerFighter.fight(enemyFighter);
        callback && callback(battleReport);
    });

    loader.addLoad('player');
    loader.addLoad('enemy');

    gPlayers.get(uid, function(_player){
        player = _player;
        loader.onLoad('player');
    });

    gPlayers.get(enemyid, function(_player){
        enemy = _player;
        loader.onLoad('enemy');
    });
}

global.fightLeagueBoss = function(uid, bossConf, bossHealth, callback) {
    if( bossHealth <= 0 || !bossConf ) {
        callback && callback();
        return;
    }
                    
    gPlayers.get(uid, function(player){
        if( !player ) {
            callback && callback(null);
            return;
        }

        var playerFighter = new Fighter();
        var bossType = 'league_boss';
        playerFighter.initWithPlayer(player, bossType);

        var enemyFighter = new Fighter();
        enemyFighter.initWithMonster('BOSS', bossConf.Id, bossConf);
        enemyFighter.setBossHealthBeforeFight(bossHealth);

        gUserInfo.updatePlayer(player);

        var battleReport = playerFighter.fight(enemyFighter);
        callback && callback(battleReport);
    });
}

global.fightLeagueDuplicate = function(uid, inspire, bossConf, hp, callback) {
    if (!bossConf || !hp) {
        callback && callback();
        return;
    }

    gPlayers.get(uid, function(player) {
        if( !player ) {
            callback && callback(null);
            return;
        }

        var playerFighter = new Fighter();
        var bossType = 'league_duplicate';
        playerFighter.initWithPlayer(player, bossType);

        if (inspire) {
             playerFighter.addAttackBeforeFight(inspire*gConfGlobal.LeagueDuplicateInspireAttack);
        }

        var enemyFighter = new Fighter();
        enemyFighter.initWithMonster('BOSS', bossConf.Id, bossConf);
        enemyFighter.setBossHealthBeforeFight(hp);

        gUserInfo.updatePlayer(player);

        var battleReport = playerFighter.fight(enemyFighter);
        callback && callback(battleReport);
    });
}

global.fightWorldBoss = function(uid, bossConf, worldboss, callback) {
    if (!bossConf || !worldboss.blood) {
        callback && callback();
        return;
    }
                    
    gPlayers.get(uid, function(player){
        if( !player ) {
            callback && callback(null);
            return;
        }

        var playerFighter = new Fighter();
        var bossType = 'world_boss';
        playerFighter.initWithPlayer(player, bossType);

        var enemyFighter = new Fighter();
        enemyFighter.initWithMonster('BOSS', bossConf.Id, bossConf);
        enemyFighter.damageFactor = worldboss.damage_factor;
        enemyFighter.setBossHealthBeforeFight(worldboss.blood);

        gUserInfo.updatePlayer(player);

        var battleReport = playerFighter.fight(enemyFighter);
        callback && callback(battleReport);
    });
}

global.fightYearBoss = function(uid, bossConf, bossHealth, callback) {
    if( bossHealth <= 0 || !bossConf ) {
        callback && callback();
        return;
    }
                    
    gPlayers.get(uid, function(player){
        if( !player ) {
            callback && callback(null);
            return;
        }

        var playerFighter = new Fighter();
        var bossType = 'year_boss';
        playerFighter.initWithPlayer(player, bossType);

        var enemyFighter = new Fighter();
        enemyFighter.initWithMonster('BOSS', bossConf.Id, bossConf);
        enemyFighter.setBossHealthBeforeFight(bossHealth);

        gUserInfo.updatePlayer(player);

        var battleReport = playerFighter.fight(enemyFighter);
        callback && callback(battleReport);
    });
}

global.verifyWordFilter = function(content, key) {
    if( typeof(content) != 'string' ) return false;
    if( config.FuckTheWordFilter ) return true;

    return common.verifyWordFilter(content, key);
}

global.requestWorld = function(query, resp, callback){
    var logicHandler = world[query.mod][query.act];
    var worldResp = {'code':0, 'desc':'', 'data':{}};
    logicHandler(query, worldResp, function(){
        resp.code = worldResp.code;
        resp.desc = worldResp.desc;
        resp.data = worldResp.data;

        callback && callback();
    });
}

/*
param delay : delay选项,参考gActivityDelay
*/
global.findActivitySchedule = function(key, delay) {
    var activityConf = gConfActivities[key];
    if (!activityConf) {
        return null;
    }

    var now = new Date();
    var nowStamp = now.getStamp();
    var passedDay = now.getDayPassed(gConfGlobalServer.ServerStartTime);
    var delayDays = activityConf.DelayDays;

    if (passedDay >= activityConf.OpenDay) {
        var startTime = activityConf.StartTime;
        var endTime = activityConf.EndTime;
        switch (delay) {
            case 1:
                endTime = activityConf.EndTime + delayDays*86400;
                break;
            case 2:
                startTime = activityConf.EndTime;
                endTime = activityConf.EndTime + delayDays*86400;
                break;
            default:
                break;
        }

        if (nowStamp >= startTime && nowStamp <= endTime) {
            return {
                'time': activityConf.StartTime, 
                'conf': activityConf.ConfId, 
                'end_time': activityConf.EndTime, 
                'open_level': activityConf.OpenLevel
            };
        }
    }

    if (activityConf.IsSchedule) {
        for (var id in gConfActivitySchedule) {
            scheduleConf = gConfActivitySchedule[id];
            if (scheduleConf.Key == key) {
                var startDay = scheduleConf.StartDay;
                var endDay = scheduleConf.EndDay;

                switch (delay) {
                    case 1:
                        endDay = scheduleConf.EndDay + delayDays;
                        break;
                    case 2:
                        startDay = scheduleConf.EndDay;
                        endDay = scheduleConf.EndDay + delayDays;
                        break;
                    default:
                        break;
                }

                if (passedDay >= startDay && passedDay <= endDay) {
                    return {
                        'time':gConfGlobalServer.ServerStartTime+(scheduleConf.StartDay-1)*86400, 
                        'conf':scheduleConf.ConfId, 
                        'end_time':gConfGlobalServer.ServerStartTime+(scheduleConf.EndDay-1)*86400,
                    };
                }
            }
        }
    }

    return null;
}

global.requestUniverse = function(query, resp, callback){
    var options = {
        host: gConfGlobalServer.UniverseHost,
        port: gConfGlobalServer.UniversePort,
        path: '/',
        method: 'POST'
    };

    var req = http.request(options, function(res) {
        var chunks = [];
        res.on('data', function(chunk){
            chunks.push(chunk);
        });

        res.on('end', function(){
            var data = Buffer.concat(chunks).toString();
            var UniverseResp = null;
            try{
                UniverseResp = JSON.parse(data); 
            }catch(error){
                ERROR('universe resp '+data);
                UniverseResp = null;
            }

            if( !UniverseResp ) {
                resp.code = 1; resp.desc='request universe error';
            }else{
                resp.code = UniverseResp.code;
                resp.desc = UniverseResp.desc;
                resp.data = UniverseResp.data;
            }

            callback && callback();
        });
    });

    req.on('error', function(err){
        resp.code = 1;
        resp.desc = 'request universe error';
        callback && callback(null);
    });

    req.end(qs.stringify({
        mod: query.mod,
        act: query.act,
        uid: query.uid,
        args: JSON.stringify(query.args || {}),
    }));
    req.end();
}

global.requestCloud = function(query, resp, callback){
    var options = {
        host: gConfGlobalServer.CloudHost,
        port: gConfGlobalServer.CloudPort,
        path: '/',
        method: 'POST'
    };

    var req = http.request(options, function(res) {
        var chunks = [];
        res.on('data', function(chunk){
            chunks.push(chunk);
        });

        res.on('end', function(){
            var data = Buffer.concat(chunks).toString();
            var UniverseResp = null;
            try{
                UniverseResp = JSON.parse(data); 
            }catch(error){
                ERROR('universe resp '+data);
                UniverseResp = null;
            }

            if( !UniverseResp ) {
                resp.code = 1; resp.desc='request universe error';
            }else{
                resp.code = UniverseResp.code;
                resp.desc = UniverseResp.desc;
                resp.data = UniverseResp.data;
            }

            callback && callback();
        });
    });

    req.on('error', function(err){
        resp.code = 1;
        resp.desc = 'request cloud error';
        callback && callback(null);
    });

    req.end(qs.stringify({
        mod: query.mod,
        act: query.act,
        uid: query.uid,
        args: JSON.stringify(query.args || {}),
    }));
    req.end();
}

//请求跨服排行服务器
global.requestCloudRank = function(query, resp, callback){
    var options = {
        host: gConfGlobalServer.CloudRankHost,
        port: gConfGlobalServer.CloudRankPort,
        path: '/',
        method: 'POST'
    };

    var req = http.request(options, function(res) {
        var chunks = [];
        res.on('data', function(chunk){
            chunks.push(chunk);
        });

        res.on('end', function(){
            var data = Buffer.concat(chunks).toString();
            var cloudResp = null;
            try{
                cloudResp = JSON.parse(data); 
            }catch(error){
                ERROR('cloudRank resp '+data);
                cloudResp = null;
            }

            if( !cloudResp ) {
                resp.code = 1; resp.desc='request cloudRank error';
            }else{
                resp.code = cloudResp.code;
                resp.desc = cloudResp.desc;
                resp.data = cloudResp.data;
            }

            callback && callback();
        });
    });

    req.on('error', function(err){
        resp.code = 1;
        resp.desc = 'request cloudRank error';
        callback && callback(null);
    });

    req.end(qs.stringify({
        mod: query.mod,
        act: query.act,
        uid: query.uid,
        std: 1,
        args: JSON.stringify(query.args || {}),
    }));
    req.end();
}

//请求王者战场服务器
global.requestChampsBattle = function(query, resp, callback){
    if (!gConfGlobalServer.ChampsBattleHost) {
        resp.code = 1; resp.desc = 'champsbattle not open'; 
        callback && callback();
        return;
    }

    var options = {
        host: gConfGlobalServer.ChampsBattleHost,
        port: gConfGlobalServer.ChampsBattlePort,
        path: '/',
        method: 'POST'
    };

    var req = http.request(options, function(res) {
        var chunks = [];
        res.on('data', function(chunk){
            chunks.push(chunk);
        });

        res.on('end', function(){
            var data = Buffer.concat(chunks).toString();
            var cloudResp = null;
            try{
                cloudResp = JSON.parse(data); 
            }catch(error){
                ERROR('champsbattle resp '+data);
                cloudResp = null;
            }

            if( !cloudResp ) {
                resp.code = 1; resp.desc='request champsbattle error';
            }else{
                resp.code = cloudResp.code;
                resp.desc = cloudResp.desc;
                resp.data = cloudResp.data;
            }

            callback && callback();
        });
    });

    req.on('error', function(err){
        resp.code = 1;
        resp.desc = 'request champsbattle error';
        callback && callback(null);
    });

    req.end(qs.stringify({
        mod: query.mod,
        act: query.act,
        uid: query.uid,
        std: 1,
        sid: config.ServerId,
        args: JSON.stringify(query.args || {}),
    }));
    req.end();
}

global.requestBattleWorld = function(query, resp, callback){
    var options = {
        host: gConfGlobalServer.BattleWorldHost,
        port: gConfGlobalServer.BattleWorldPort,
        path: '/',
        method: 'POST'
    };

    var req = http.request(options, function(res) {
        var chunks = [];
        res.on('data', function(chunk){
            chunks.push(chunk);
        });

        res.on('end', function(){
            var data = Buffer.concat(chunks).toString();
            var BattleWorldResp = null;
            try{
                BattleWorldResp = JSON.parse(data); 
            }catch(error){
                ERROR('battleworld resp '+data);
                BattleWorldResp = null;
            }

            if( !BattleWorldResp ) {
                resp.code = 1; resp.desc='request battleworld error';
            }else{
                resp.code = BattleWorldResp.code;
                resp.desc = BattleWorldResp.desc;
                resp.data = BattleWorldResp.data;
            }

            callback && callback();
        });
    });

    req.on('error', function(err){
        resp.code = 1;
        resp.desc = 'request battleworld error';
        callback && callback(null);
    });

    req.end(qs.stringify({
        mod: query.mod,
        act: query.act,
        uid: query.uid,
        args: JSON.stringify(query.args || {}),
    }));
    req.end();
}

global.requestServerMine = function(query, resp, callback){
    var options = {
        host: gConfGlobalServer.ServerMineHost,
        port: gConfGlobalServer.ServerMinePort,
        path: '/',
        method: 'POST'
    };

    var req = http.request(options, function(res) {
        var chunks = [];
        res.on('data', function(chunk){
            chunks.push(chunk);
        });

        res.on('end', function(){
            var data = Buffer.concat(chunks).toString();
            var ServerMineResp = null;
            try{
                ServerMineResp = JSON.parse(data); 
            }catch(error){
                ERROR('servermine resp '+data);
                ServerMineResp = null;
            }

            if( !ServerMineResp ) {
                resp.code = 1; resp.desc='request servermine error';
            }else{
                resp.code = ServerMineResp.code;
                resp.desc = ServerMineResp.desc;
                resp.data = ServerMineResp.data;
            }

            callback && callback();
        });
    });

    req.on('error', function(err){
        resp.code = 1;
        resp.desc = 'request servermine error';
        callback && callback(null);
    });

    req.end(qs.stringify({
        mod: query.mod,
        act: query.act,
        uid: query.uid,
        args: JSON.stringify(query.args || {}),
    }));
    req.end();
}

global.doKaiShuiPromotion = function(player){
    if (!player.open_session_key) {
        return;
    }

    var task = {
        1 : 6, // 玩家等级达到6级 
    };
    
    var host = 'http://mdc.he-games.com/kaishui_debug.php';

    var user = player.user;
    var loginCount = user.activity.login_count; 

    gDBPlat.findOne({uid:user._id},{}, function(err, doc){
        if( err || !doc ) {
            return; 
        } 
        
        var openid = doc._id;

        for( var id in task ) {
            var id = +id;
            if( user.activity.kaishui_promotion.task[id]) continue;
            if (1 == id && (!user.status.level || (user.status.level < task[id]))) continue;
            
            var url = util.format('%s?session=%s&openid=%s&task_id=%d', host, player.open_session_key, openid, +id);
            common.httpGet(url, function(data){}, false); 
        }
    
    });
}

global.requestGamex = function(path, resp, callback) {
    var url = util.format('http://%s/%s', gConfGlobalServer.GamexURL, path);
    common.httpGet(url, function(data) {
        if (!data || 'error' == data) {
            resp.code = 1;
            resp.desc = "request gamex error";
        } else {
            resp.code = data.code;
            resp.desc = data.desc;
            resp.data = data.data || {};
        }
        callback && callback();
    }, true);
}

global.writeRecord = function(obj) {
    RECORD(obj);
    //var url = util.format('%s/gameRecord?sid=%d&data=%s', 'http://172.31.244.3:8000', config.ServerId, obj);
    //common.httpGet(url, function(data) {}, false);
}

global.writeAudit = function(obj) {
    AUDIT(obj);
}

global.writeDBLog = function(obj) {
    gDBLog.update({'act':obj.act, 'uid':obj.uid, 'sub':obj.sub}, obj, {upsert:true}, function(err, result) {});
}


function timer_hour() {
    setInterval(function(){
        objectForEach(gConfActivities, function(key, conf) {
            if (conf.DelayDays && findActivitySchedule(key, 2)) {
                gMessage.addSystemMessage('activity_delaytime', [conf.Name]);
            }
        });

        logic['battleworld'].auto_register();
    }, 60*60*1000);
}

